/**
 ****************************************************************
 * @file
 *
 * @brief
 *
 * @author
 *
 ****************************************************************
 */
#include <stdio.h>
#include <string.h>
#include "iso14443a.h"
#include "iso14443b.h"
#include "iso14443_4.h"
#include "emv_contectless.h"
#include "nfc_hal_debug.h"
#include "define.h"
#include "nfc_hal_dpo.h"
#include "user_includes.h"
emv_test_t g_emv_test;
uint8_t g_emv_runing;
uint8_t iop_mode_flag = 0;
uint8_t DPO_flag=0;

extern uint8_t EMV_DEBUG_LOG;

#define PICC_CID 0x00 // 0~14 随意指定

uint8_t  g_protocol_t_b4;

picc_det_t g_picc_det;
uint8_t g_ATQx[16];

uint8_t iop_flag = 1;

//EMV test 0326
//02 00A404000E 325041592E5359532E4444463031 00
uint8_t SELECT_PPSE[] = {/*0x02, */0x00,0xA4, 0x04, 0x00, 0x0E,
                                   '2', 'P', 'A', 'Y', '.',
                                   'S', 'Y', 'S', '.',
                                   'D', 'D', 'F', '0', '1',
                                   0x00
                        };

hal_nfc_regval_t EMV_typeA_configs[] =
{
    {0, 0x01, 0x00},  //打开接收，芯片处于Ready状态
    {0, 0x02, 0x00},  //IRQ同向
    {0, 0x03, 0x80},  //最高位bit7置1，配置IRQ为推挽输出，根据实际场景可不配
    {0, 0x08, 0x00},  //清除Mifare加密状态
    {1, 0x11, 0x3D},  //定义CRC_Processor执行CalcCRC指令的预置，A/M卡低两位写01；B卡低两位写11
    {1, 0x12, 0x00},  //定义发送数据的帧结构
    {1, 0x13, 0x00},  //定义接收数据的帧结构
    {1, 0x15, 0x40},  //输出调制信号类型，bit6置1是OOK(A/V卡)，置0是ASK(B/F卡)
    {1, 0x17, 0x92},  //配置接收等待时间
//    {1, 0x19, 0x2d},
    {1, 0x1D, 0xA3},  //高通滤波器带宽影响刷卡
    {2, 0x26, 0x48},  //手动增益调整值，配合第四页35寄存器
    {2, 0x28, 0xA0},  //发射场强调整
    {4, 0x35, 0xe0},  //增益配置
    {4, 0x36, 0x80},	
    {4, 0x3A, 0x05},  //低三位配置相位补偿，IQ翻转影响刷卡
    {4, 0x3B, 0x6D},  //bit6置1，EMV认证用；bit6置0，正常模式用；bit5:3 噪声信号解调比，EMV认证测灵敏度时建议置101/110/111
    {4, 0x3F, 0x52},  //bit1：Rxwait扩展位使能
    {6, 0x33, 0x10}, 	//bit5置1，ARC才会调整
    {6, 0x3F, 0x70},  //bit6:4 A波下降沿调整
    {7, 0x31, 0x20},  //LPF增益控制位，严重影响刷卡
    {7, 0x32, 0x68},  //接收内部Rtune调整
    {7, 0x38, 0x5E},  //bit0=0关闭调制深度自适应功能
    {7, 0x3D, 0x68},  //bit6:使能模拟相位校准与调整低通滤波器带宽，影响刷卡
    {7, 0x3E, 0x80},  //相位校准自动补偿bit7=1；手动补偿bit7=0
    {8, 0x34, 0x69},  //ARC使能
    {8, 0x39, 0xC6},  //多卡冲突调整
    {10, 0x31, 0x30},  //TA上升沿步长
    {10, 0x32, 0x0f},  //TA上升沿步数
    {10, 0x33, 0x30},  //TA下降沿步长
    {10, 0x34, 0xff},  //TA下降沿步数
};

hal_nfc_regval_t EMV_typeB_configs[] =
{
    {0, 0x01, 0x00},  //打开接收，芯片处于Ready状态
    {0, 0x02, 0x00},  //IRQ同向
    {0, 0x03, 0x80},  //最高位bit7置1，配置IRQ为推挽输出，根据实际场景可不配
    {0, 0x08, 0x00},
    {0, 0x0D, 0x00},  //低三位只影响B卡且只能配置000；A卡无法修政
    {1, 0x11, 0x3F},  //定义CRC_Processor执行CalcCRC指令的预置，A/M卡低两位写01；B卡低两位写11
    {1, 0x12, 0x83},  //定义发送数据的帧结构
    {1, 0x13, 0x83},  //定义接收数据的帧结构
    {1, 0x15, 0x00},  //输出调制信号类型，置1是OOK(A/V；置0是ASK(B/F)
    {1, 0x17, 0x92},  //接收等待时间
    {1, 0x1D, 0xA3},  //高通滤波器带宽影响刷卡
    {1, 0x1E, 0x03},  //B卡专用，SOF与EGT定义，新方案这一位有改动要配置成03
    {2, 0x26, 0x48},  //手动增益调整值，配合第四页35寄存器
    {2, 0x28, 0xA0},  //P管发射场强调整
    {2, 0x29, 0x32},  //P管MOD信号调整，改变调制深度
    {4, 0x35, 0xE0},  //增益配置
    {4, 0x36, 0x80},
    {4, 0x3A, 0x05},  //低三位配置相位补偿，IQ翻转影响刷卡
    {4, 0x3F, 0x52},  //bit1：Rxwait扩展位使能
    {7, 0x31, 0x21},  //LPF增益控制位，严重影响刷卡
    {7, 0x32, 0x68},  //接收内部Rtune调整
    {7, 0x38, 0x5F},  //bit0调制深度自适应使能，若不使能，则配第六页33=10
    {7, 0x39, 0xC9},  //目标调制深度设置
    {7, 0x3D, 0x68},  //bit6:使能模拟相位校准与调整低通滤波器带宽，影响刷卡
    {7, 0x3E, 0x80},  //相位校准补偿值使能
    {8, 0x34, 0x69},  //ARC使能
//    {8, 0x3C, 0xB3},  //B卡冲突寄存器与使能位
//    {8, 0x3D, 0x03},  //B卡冲突寄存器相关配置
    {10, 0x35, 0x21},  //TB上升沿步长
    {10, 0x36, 0xff},  //TB上升沿步数
    {10, 0x38, 0x1D},  //TB下降沿步长
    {10, 0x39, 0xff},  //TB下降沿步数
};




int emv_polling(void);
int emv_anticollision(void);
int emv_activate_picc(void);
int emv_remove_picc(void);
void emv_reset_field(void);
int picc_detect(void);
int emv_loopback(void);

void emv_power_off_field(void);
void emv_transac_a(void);
void emv_transac_b(void);



extern void make_packet(uint8_t cmd, uint8_t *buf, uint8_t len);
extern uint8_t iop_mode_flag;

int emv_contectless()
{
    int status;

    status = picc_detect(); /* Detect Card  */

    if (0 == status) {
        status = emv_loopback(); /* EMV Loopback*/
        if (0 == status) {
            emv_remove_picc();  /* Remove Picc */
            /* emv3.0 Interoperability Testing */
            if (iop_mode_flag)
            {
                //Hal_Beep(400);
            }
        }
        else if (-2 == status) {
            emv_power_off_field();
            /* emv3.0 Interoperability Testing */
            if(iop_mode_flag)
            {
                // Hal_Beep(100);
                // delay_ms(100);
                // Hal_Beep(100);
            }
        }
        else {
            emv_reset_field(); /* Rest Field ,Poweroff Picc */
            /* emv3.0 Interoperability Testing */
            if(iop_mode_flag)
            {
                // Hal_Beep(100);
                // delay_ms(100);
                // Hal_Beep(100);
            }
        }
    }

    return 0;
}

int picc_detect()
{
    pcd_default_info();
    memset(&g_picc_det, 0, sizeof(g_picc_det));
    g_protocol_t_b4 = 0xFF; //TB304.14

    if (-1 == emv_polling()) {
//      led_fail_on();
        return -1;
    } else {
//      led_success_on();
    }
    if (-1 == emv_anticollision())
        goto reset_picc;
    if (-1 == emv_activate_picc())
        goto reset_picc;

    return 0;

reset_picc:
    emv_reset_field();
    return -1;
}

void emv_analog_loop()
{
    do {

        if (g_emv_test.opt_count <= 0) {
            memset(&g_emv_test, 0, sizeof(g_emv_test));
            break;
        } else {
            g_emv_test.opt_count--;
            make_packet(COM_PKT_CMD_LOOP_COUNT, (uint8_t *)&g_emv_test.opt_count, sizeof(g_emv_test.opt_count));
        }

        //reset
        if (g_emv_test.reset_test == TRUE) {
            drv_interface.hw_msleep(T_RESET);
            emv_reset_field();
            // printf("\r\n field reset after 20ms ");
            drv_interface.hw_msleep(20);
            break;
        }
        if (g_emv_test.polling_test == TRUE) {
            //
            emv_contectless();
            break;
        }
        if (g_emv_test.wupa_test == TRUE) {
            drv_interface.hw_msleep(T_PAUSE);
            hal_nfc_config(EMV_typeA_configs, sizeof(EMV_typeA_configs)/sizeof(hal_nfc_regval_t));
            pcd_request(PICC_REQALL, g_ATQx);
            break;
        }
        if (g_emv_test.wupb_test == TRUE) {
            drv_interface.hw_msleep(T_PAUSE);
            hal_nfc_config(EMV_typeB_configs, sizeof(EMV_typeB_configs)/sizeof(hal_nfc_regval_t));
            pcd_request_b(ISO14443_3B_REQALL, 0, 0, g_ATQx);
            break;
        }
        if (g_emv_test.poweroff_test == TRUE) {
            drv_interface.hw_msleep(T_RESET);
            emv_power_off_field();
            break;
        }
        if (g_emv_test.wupa_rats_test == TRUE) {
            g_picc_det.type_a = TRUE;
            g_picc_det.type_b = FALSE;

            drv_interface.hw_msleep(T_RESET);
            hal_nfc_config(EMV_typeA_configs, sizeof(EMV_typeA_configs)/sizeof(hal_nfc_regval_t));

            if (-1 != emv_anticollision()) {
                emv_activate_picc();
            }
            break;
        }
        if (g_emv_test.wupb_attrib_test == TRUE) {
            g_picc_det.type_a = FALSE;
            g_picc_det.type_b = TRUE;

            drv_interface.hw_msleep(T_RESET);
            hal_nfc_config(EMV_typeB_configs, sizeof(EMV_typeB_configs)/sizeof(hal_nfc_regval_t));

            if (-1 != emv_anticollision()) {
                emv_activate_picc();
            }
            break;
        }
        if (g_emv_test.transac_a == TRUE) {
            emv_transac_a();
            break;
        }
        if (g_emv_test.transac_b == TRUE) {
            emv_transac_b();
            break;
        }

    } while (0);

}

int emv_polling()
{
    int status;
    if(EMV_DEBUG_LOG)
        printf("emv_polling\n");

    do {
        //typea polling
        if (g_picc_det.type_a == TRUE)
        {
            hal_nfc_config(EMV_typeA_configs, sizeof(EMV_typeA_configs)/sizeof(hal_nfc_regval_t));
            return 0;
        }
        else
        {
            drv_interface.hw_msleep(T_PAUSE);
            hal_nfc_config(EMV_typeA_configs, sizeof(EMV_typeA_configs)/sizeof(hal_nfc_regval_t));
            status = pcd_request(PICC_REQALL, g_ATQx);

            if (status == HAL_STATUS_OK || status == HAL_STATUS_PROTOCOL_ERR ||
                    status == HAL_STATUS_COLLERR || status == HAL_STATUS_INTEGRITY_ERR ||
                    status == HAL_STATUS_BITCOUNT_ERR || status == HAL_STATUS_FRAMINGERR) {
                // If the PCD receives any response (correct or not) to the WUPA command, then The PCD shall set TYPE_A equal to 1 (symbol 6). //TA301.13 TA301.00 TA301.01
                g_picc_det.type_a = TRUE;
                status = pcd_hlta();
            }
        }
        //typeb polling
        if (g_picc_det.type_b == TRUE) {
            hal_nfc_config(EMV_typeB_configs, sizeof(EMV_typeB_configs)/sizeof(hal_nfc_regval_t));
            return 0;
        } else {
            drv_interface.hw_msleep(T_PAUSE);
            hal_nfc_config(EMV_typeB_configs, sizeof(EMV_typeB_configs)/sizeof(hal_nfc_regval_t));
            status = pcd_request_b(ISO14443_3B_REQALL, 0, 0, g_ATQx);
            if (status == HAL_STATUS_OK || status == HAL_STATUS_COLLERR ||
                    status == HAL_STATUS_PROTOCOL_ERR || status == HAL_STATUS_ERR ||
                    status == HAL_STATUS_FRAMINGERR || status == HAL_STATUS_INTEGRITY_ERR) {
                // If the PCD receives any response (correct or not) to the WUPB command, then The PCD shall set TYPE_B equal to 1 (symbol 12). //EMV_TEST TB301.01 TB301.10 TB301.11 TB301.13
                g_picc_det.type_b = TRUE;

            }
        }

    } while (g_picc_det.type_a == TRUE || g_picc_det.type_b == TRUE);

    return -1;
}

int emv_anticollision()
{
    int status;
    uint8_t uid_size;
    uint8_t cnt;


    if(EMV_DEBUG_LOG)
        printf("emv_anti\n");

    if (g_picc_det.type_a == TRUE && g_picc_det.type_b == TRUE) {
        //emv collision
        printf("ERR:multi type=1\n");
        return -1;
    }

    if (g_picc_det.type_a == TRUE) {
        cnt = 0;
        do {
            drv_interface.hw_msleep(T_PAUSE);
            status = pcd_request(PICC_REQALL, g_ATQx);
        } while (status == HAL_STATUS_TIMEOUT && ++cnt < 3);//timeout retransmit
        if (status == HAL_STATUS_OK) {
            uid_size = ((g_ATQx[0] & (BIT(7) | BIT(6))) >> 6) + 1; // UID size
            cnt = 0;
            do {
                status = pcd_cascaded_anticoll(PICC_ANTICOLL1, 0, g_ATQx + 2);

                if (status == HAL_STATUS_TIMEOUT) {
                    drv_interface.hw_msleep(T_RETRANSMISSION);// EMV_30 modify
                }
            } while (status == HAL_STATUS_TIMEOUT && ++cnt < 3);//timeout retransmit
            //EMV_TEST
            if (status == HAL_STATUS_OK && (g_ATQx[2] == 0x88) && uid_size == 1) {
                //ERR:single uid,but uid0 == 88 (CT)
                status = PROTOCOL_ERR;
            }
            if (status == HAL_STATUS_OK) {
                cnt = 0;
                do {
                    status = pcd_cascaded_select(PICC_ANTICOLL1, g_ATQx + 2, &g_ATQx[14]);
                    if (status == HAL_STATUS_TIMEOUT) {
                        drv_interface.hw_msleep(T_RETRANSMISSION);// EMV_30 modify
                    }
                } while (status == HAL_STATUS_TIMEOUT && ++cnt < 3);//timeout retransmit

                if (status == HAL_STATUS_OK && (g_ATQx[14] & BIT(2)) && uid_size == 1) {
                    //ERR:single uid,but indicate not complete
                    status = PROTOCOL_ERR;
                }

                if (status == HAL_STATUS_OK && (g_ATQx[14] & BIT(2))) {
                    cnt = 0;
                    do {
                        memcpy(g_ATQx + 6, g_ATQx + 2, 4);
                        status = pcd_cascaded_anticoll(PICC_ANTICOLL2, 0, g_ATQx + 6);
                    } while (status == HAL_STATUS_TIMEOUT && ++cnt < 3);//timeout retransmit
                    //EMV_TEST
                    if (status == HAL_STATUS_OK && (g_ATQx[6] == 0x88) && uid_size == 2) {
                        //ERR:double uid,but uid0 == 88 (CT)
                        status = PROTOCOL_ERR;
                    }
                    if (status == HAL_STATUS_OK) {
                        cnt = 0;
                        do {
                            status = pcd_cascaded_select(PICC_ANTICOLL2, g_ATQx + 6, &g_ATQx[14]);
                        } while (status == HAL_STATUS_TIMEOUT && ++cnt < 3);//timeout retransmit
                    }
                }
                if (status == HAL_STATUS_OK && (g_ATQx[14] & BIT(2)) && uid_size == 2) {
                    //ERR:double uid,but indicate not complete
                    status = PROTOCOL_ERR;
                }

                if (status == HAL_STATUS_OK && (g_ATQx[14] & BIT(2))) {
                    cnt = 0;
                    do {
                        memcpy(g_ATQx + 10, g_ATQx + 6, 4);
                        status = pcd_cascaded_anticoll(PICC_ANTICOLL3, 0, g_ATQx + 10);
                    } while (status == HAL_STATUS_TIMEOUT && ++cnt < 3);//timeout retransmit
                    //EMV_TEST
                    if (status == HAL_STATUS_OK && (g_ATQx[10] == 0x88) && uid_size == 3) {
                        //ERR:triple uid,but uid0 == 88 (CT)
                        status = PROTOCOL_ERR;
                    }
                    if (status == HAL_STATUS_OK) {
                        cnt = 0;
                        do {
                            status = pcd_cascaded_select(PICC_ANTICOLL3, g_ATQx + 10, &g_ATQx[14]);
                        } while (status == HAL_STATUS_TIMEOUT && ++cnt < 3);//timeout retransmit

                    }
                }
                if (status == HAL_STATUS_OK && (g_ATQx[14] & BIT(2)) && uid_size == 3) {
                    //ERR:triple uid,but indicate not complete
                    status = PROTOCOL_ERR;
                }
                if (status == HAL_STATUS_OK && !(g_ATQx[14] & BIT(2)) && (g_ATQx[14] & BIT(5))) {
                    //Select ok and PICC compliant with ISO/IEC 14443-4
                    return 0;
                } else if (status == HAL_STATUS_OK && !(g_ATQx[14] & BIT(2)) && !(g_ATQx[14] & BIT(5))) {
                    printf("ERR: not compliant 14443-4\n");
                }
            }
        }
    } else if (g_picc_det.type_b == TRUE) {
        cnt = 0;
        do {
            drv_interface.hw_msleep(T_PAUSE);
            status = pcd_request_b(ISO14443_3B_REQALL, 0, 0, g_ATQx);
        } while (status == HAL_STATUS_TIMEOUT && ++cnt < 3);//timeout retransmit

        if (status == HAL_STATUS_OK) {
            return 0;
        }
    }

    return -1;
}

int emv_activate_picc()
{
    int status;
    uint8_t cnt;
    uint8_t ats[16];

    if(EMV_DEBUG_LOG)
        printf("emv_activate\n");

    if (g_picc_det.type_a == TRUE) {
        cnt = 0;
        do {
            status = pcd_rats_a(0, ats);
            pcd_delay_sfgi(3);//EMV2.6 tMIN,RETRANSMISSION 3 ms
        } while (status == HAL_STATUS_TIMEOUT && ++cnt < 3);
        if (status == HAL_STATUS_OK) {
            return 0;
        }
    } else if (g_picc_det.type_b == TRUE) {
        //attrib ok in emv_anticollision
        cnt = 0;

        do {
            pcd_delay_sfgi(g_pcd_module_info.ui_sfgi);
            pcd_set_tmo(4);
            status = pcd_attri_b(&g_ATQx[1], 0, g_ATQx[10] & 0x0f, PICC_CID, g_ATQx);

        } while ((status == HAL_STATUS_TIMEOUT) && (++cnt < 3));//timeout retransmit

        if (status == HAL_STATUS_OK) {
            return 0;
        }
    }

    return -1;
}

int emv_remove_picc()
{
    int status;
    uint8_t cnt;

    emv_reset_field();
    drv_interface.hw_msleep(T_PAUSE);//TB003

    cnt = 0;
    while (1) {
        if (g_picc_det.type_a == TRUE) {
            status = pcd_request(PICC_REQALL, g_ATQx);
            if (status == HAL_STATUS_OK || status == HAL_STATUS_PROTOCOL_ERR ||
                    status == HAL_STATUS_COLLERR || status == HAL_STATUS_INTEGRITY_ERR ||
                    status == HAL_STATUS_BITCOUNT_ERR) {
                // If the PCD receives any response (correct or not) to the WUPA command, then The PCD shall set TYPE_A equal to 1 (symbol 6). //TA301.13 TA301.00 TA301.01
                cnt = 0;
                status = pcd_hlta();
                drv_interface.hw_msleep(T_PAUSE);
            } else {
                cnt++;
                if (cnt < 3) {
                    drv_interface.hw_msleep(T_RETRANSMISSION);
                }
            }
        } else if (g_picc_det.type_b == TRUE) {
            //drv_interface.hw_msleep(T_PAUSE);
            status = pcd_request_b(ISO14443_3B_REQALL, 0, 0, g_ATQx);
            if (status == HAL_STATUS_OK || status == HAL_STATUS_COLLERR ||
                    status == HAL_STATUS_PROTOCOL_ERR || status == HAL_STATUS_ERR) {
                // If the PCD receives any response (correct or not) to the WUPB command, then The PCD shall set TYPE_B equal to 1 (symbol 12). //EMV_TEST TB301.01 TB301.10 TB301.11 TB301.13
                //drv_interface.hw_msleep(T_PAUSE);
                drv_interface.hw_msleep(T_PAUSE);//TB003
                cnt = 0;
            } else {
                cnt++;
                if (cnt < 3) {
                    drv_interface.hw_msleep(T_RETRANSMISSION);
                }
            }
        }

        if (cnt >= 3) {
            if(EMV_DEBUG_LOG)
                printf("emv_remove_picc ok\n");

            return 0;
        }
    }

}


void emv_reset_field()
{
    hal_nfc_antenna_off();
    drv_interface.hw_msleep(T_RESET);
    hal_nfc_antenna_on();
}

void emv_power_off_field()
{
    hal_nfc_antenna_off();
    drv_interface.hw_msleep(20);//mdelay(T_RESETDELAY);//must > 15 ms
    hal_nfc_antenna_on();
}

void emv_transac_a(void)
{
    uint8_t test_i_block_1[] = {0x02, 0x00, 0xA4, 0x04, 0x00, 0x0E, 0x32, 0x50, 0x41, 0x59, 0x2E, 0x53, 0x59, 0x53, 0x2E, 0x44, 0x44, 0x46, 0x30, 0x31, 0x00};
    uint8_t test_i_block_2[] = {0x03, 0x00, 0xA4, 0x04, 0x00, 0x0C, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x00};
    hal_nfc_transceive_t pi;
    uint8_t ats[16];

    pcd_default_info();
    memset(&g_picc_det, 0, sizeof(g_picc_det));
    g_protocol_t_b4 = 0xFF;

    drv_interface.hw_msleep(100);

    hal_nfc_config(EMV_typeA_configs, sizeof(EMV_typeA_configs)/sizeof(hal_nfc_regval_t));
    pcd_request(PICC_REQALL, g_ATQx);
    pcd_hlta();
    hal_nfc_config(EMV_typeB_configs, sizeof(EMV_typeB_configs)/sizeof(hal_nfc_regval_t));
    pcd_request_b(ISO14443_3B_REQALL, 0, 0, g_ATQx);
    hal_nfc_config(EMV_typeA_configs, sizeof(EMV_typeA_configs)/sizeof(hal_nfc_regval_t));
    pcd_request(PICC_REQALL, g_ATQx);
    pcd_cascaded_anticoll(PICC_ANTICOLL1, 0, g_ATQx + 2);
    // set default uuid
    g_ATQx[2] = 0x27;
    g_ATQx[3] = 0xE9;
    g_ATQx[4] = 0x3B;
    g_ATQx[5] = 0x11;
    pcd_cascaded_select(PICC_ANTICOLL1, g_ATQx + 2, &g_ATQx[14]);
    pcd_rats_a(0, ats);

    //tx test i block 1
    hal_nfc_write_register(REG_TPRESCALER, (192) & 0xFF);
    hal_nfc_write_register(REG_TMODE, BIT(7) | (((256 + 192)>>8) & 0xFF));

    pi.mf_length = sizeof(test_i_block_1);
    memcpy(pi.mf_data, test_i_block_1, pi.mf_length);
    pi.mf_command = PCD_TRANSCEIVE;
    pcd_com_transceive(&pi);

    //tx test iblock 2
    pi.mf_length = sizeof(test_i_block_2);
    memcpy(pi.mf_data, test_i_block_2, pi.mf_length);
    pi.mf_command = PCD_TRANSCEIVE;
    pcd_com_transceive(&pi);
}


void emv_transac_b(void)
{
    uint8_t test_i_block_1[] = {0x02, 0x00, 0xA4, 0x04, 0x00, 0x0E, 0x32, 0x50, 0x41, 0x59, 0x2E, 0x53, 0x59, 0x53, 0x2E, 0x44, 0x44, 0x46, 0x30, 0x31, 0x00};
    uint8_t test_i_block_2[] = {0x03, 0x00, 0xA4, 0x04, 0x00, 0x0C, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x00};
    hal_nfc_transceive_t mf_com_data;
    hal_nfc_transceive_t *pi = &mf_com_data;

    pcd_default_info();
    memset(&g_picc_det, 0, sizeof(g_picc_det));
    g_protocol_t_b4 = 0xFF;

    drv_interface.hw_msleep(90);//每组之间间隔100ms

    hal_nfc_config(EMV_typeB_configs, sizeof(EMV_typeB_configs)/sizeof(hal_nfc_regval_t));
    pcd_request_b(ISO14443_3B_REQALL, 0, 0, g_ATQx);
    hal_nfc_config(EMV_typeA_configs, sizeof(EMV_typeA_configs)/sizeof(hal_nfc_regval_t));
    pcd_request(PICC_REQALL, g_ATQx);

    hal_nfc_config(EMV_typeB_configs, sizeof(EMV_typeB_configs)/sizeof(hal_nfc_regval_t));
    pcd_request_b(ISO14443_3B_REQALL, 0, 0, g_ATQx);

    // set default pupi
    g_ATQx[1] = 0x46;
    g_ATQx[2] = 0xB5;
    g_ATQx[3] = 0xC7;
    g_ATQx[4] = 0xA0;
    pcd_attri_b(&g_ATQx[1], 0, 0x00, PICC_CID, g_ATQx);

    //tx test i block 1
    pcd_set_tmo(2);
    pi->mf_length = sizeof(test_i_block_1);
    memcpy(pi->mf_data, test_i_block_1, pi->mf_length);
    pi->mf_command = PCD_TRANSCEIVE;
    pcd_com_transceive(pi);

    //tx test iblock 2
    pcd_set_tmo(2);
    pi->mf_length = sizeof(test_i_block_2);
    memcpy(pi->mf_data, test_i_block_2, pi->mf_length);
    pi->mf_command = PCD_TRANSCEIVE;
    pcd_com_transceive(pi);
}


int emv_loopback()
{
    int status;
    uint8_t loop_buf[256*2];
    unsigned int tx_len;
    unsigned int rx_len;

    if(EMV_DEBUG_LOG)
        printf("emv_loopback\n");
    //Send SELECT_PPSE
    memcpy(loop_buf, SELECT_PPSE, sizeof(SELECT_PPSE));
    tx_len = sizeof(SELECT_PPSE);

    do {
        status = ISO14443_4_HalfDuplexExchange(&g_pcd_module_info, loop_buf, tx_len, loop_buf, &rx_len);

        if (status == HAL_STATUS_OK) {

            if (rx_len < 3) {
                iop_flag = 1;
                printf("ERR:Unsuport loopback packet\n");
                return -1;
            } else if (loop_buf[1] == 0x70) {
                //EOT packet
                iop_flag = 1;
                return 0;
            }
            else if (loop_buf[1] == 0x72) {
                iop_flag = 1;
                return -2;
            }
            else if (iop_flag == 1) {
                //loopback
//                Hal_Beep(100);
                iop_flag = 0;
                tx_len = rx_len - 2;
            } else {
                tx_len = rx_len - 2;
            }

        } else {
            printf("ERR:emv_loopback\n");
            break;
        }

    } while (1);

    return -1; // Error return
}

uint8_t PAGE;//更新换页寄存器的页码
uint8_t GetPage(uint8_t value)
{
    switch(value)
    {
    case 0x5E:
        return 4;
    case 0xAE:
        return 5;
    case 0x5A:
        return 6;
    case 0xA5:
        return 7;
    case 0x55:
        return 8;
    case 0x95:
        return 9;
    case 0x35:
        return 10;
    default:
        break;
    }
    return 0;
}

void emv_cmd_process(void *pkt)
{
    pc_tx_pkt *ppkt = (pc_tx_pkt *)pkt;
    switch (ppkt->cmd)
    {
    case COM_PKT_CMD_EMV_READ_REG: {
        if(EMV_TEST)
        {
            reg_pkt_s reg_pkt;
            uint8_t   reg[2];
            reg_pkt.addr=ppkt->datu.reg.addr;   //get addr
            reg_pkt.page=ppkt->datu.reg.rw_dat; //get page
    
            reg[0]=reg_pkt.addr;    //the upper tester still use two bytes of prama.
      
            reg_pkt.reg_value = hal_nfc_get_register(reg_pkt.page,reg_pkt.addr,1);
            reg[1]=reg_pkt.reg_value;
    
            make_packet(COM_PKT_CMD_EMV_READ_REG, (u8 *)&reg, sizeof(reg));
            
        }
        break;
    }
    case COM_PKT_CMD_EMV_WRITE_REG: {
        if(EMV_TEST)
        {
            unsigned char* regpkt = (void*)pkt;
            
            extern void Push_RegConfig(hal_nfc_regval_t regconfig);
            hal_nfc_regval_t regitem;
            regitem.addr = regpkt[3];
            regitem.value = regpkt[4];
            regitem.page = regpkt[5];
            Push_RegConfig(regitem);
            hal_nfc_set_register(regitem.page,regitem.addr,regitem.value,1);

        }
        break;
    }
    case COM_PKT_CMD_EMV_TEST_START: {
        hal_nfc_antenna_on();
        printf("Test Start.\n");
        g_emv_runing = TRUE;
        break;
    }
    case COM_PKT_CMD_EMV_TEST_IOP: {
        hal_nfc_antenna_on();
        printf("Test Start.\n");
        g_emv_runing = TRUE;
        iop_mode_flag = 1;
        break;
    }
    case COM_PKT_CMD_EMV_TEST_STOP: {
        printf("Test Stop.Field OFF \n");
        g_emv_runing = FALSE;
        memset(&g_emv_test, 0, sizeof(g_emv_test));
        iop_mode_flag = 0;
        hal_nfc_antenna_off();
        rf_dpo_switch(false);
        break;
    }
    case COM_PKT_CMD_EMV_TEST_PAUSE: {

        if (ppkt->datu.dat[0] == 1)
        {
            printf("Test Pause.\n");
            g_emv_test.test_pause = TRUE;
        }

        break;
    }

    case COM_PKT_CMD_CARRIER_TEST: {
     
        //carrier start
        printf("Carrier On.\n");
        hal_nfc_pcd_reset();
        hal_nfc_antenna_on();
				hal_nfc_set_register(2,0x28,0xf0,1);
//        rf_dpo_switch(true);
//        DPO_flag=1; 
 
        break;
    }
    case COM_PKT_CMD_POLLING_TEST: {
        printf("Polling Start..");
        hal_nfc_antenna_on();
        memcpy(&g_emv_test.opt_count, &ppkt->datu.dat[1], sizeof(g_emv_test.opt_count));
        g_emv_test.opt_count=htonl(g_emv_test.opt_count);
        if (g_emv_test.opt_count == 0)
        {
            g_emv_test.opt_count = 0xffffffff;
        }
        else
        {

        }

        g_emv_test.polling_test = TRUE;
        printf("count: %d\n", g_emv_test.opt_count);
        break;
    }
    case COM_PKT_CMD_RESET_TEST: {
        printf("Reset Start..");
        memcpy(&g_emv_test.opt_count, &ppkt->datu.dat[1], sizeof(g_emv_test.opt_count));
        g_emv_test.opt_count=htonl(g_emv_test.opt_count);
        if (g_emv_test.opt_count == 0)
        {
            g_emv_test.opt_count = 0xffffffff;

        }
        else
        {

        }

        g_emv_test.reset_test = TRUE;
        printf("count: %d\n", g_emv_test.opt_count);
        break;
    }
    case COM_PKT_CMD_WUPA_TEST: {
        hal_nfc_config(EMV_typeA_configs, sizeof(EMV_typeA_configs)/sizeof(hal_nfc_regval_t));
        hal_nfc_antenna_on();
        printf("Wupa Start..");
        memcpy(&g_emv_test.opt_count, &ppkt->datu.dat[1], sizeof(g_emv_test.opt_count));
        g_emv_test.opt_count=htonl(g_emv_test.opt_count);
        if (g_emv_test.opt_count == 0)
        {
            g_emv_test.opt_count = 0xffffffff;
        }
        else
        {

        }

        g_emv_test.wupa_test = TRUE;
        printf("count: %d\n", g_emv_test.opt_count);

        break;
    }

    case COM_PKT_CMD_WUPB_TEST: {
        hal_nfc_config(EMV_typeB_configs, sizeof(EMV_typeB_configs)/sizeof(hal_nfc_regval_t));
        hal_nfc_antenna_on();
        printf("Wupb Start..");
        memcpy(&g_emv_test.opt_count, &ppkt->datu.dat[1], sizeof(g_emv_test.opt_count));
        g_emv_test.opt_count=htonl(g_emv_test.opt_count);

        if (g_emv_test.opt_count == 0)
        {
            g_emv_test.opt_count = 0xffffffff;
        }
        else
        {

        }

        g_emv_test.wupb_test = TRUE;
        printf("count: %d\n", g_emv_test.opt_count);

        break;
    }

    case COM_PKT_CMD_PRE_VALIDATION: {
        printf("Pre-validation Start..\n");
        if (HAL_STATUS_OK == emv_contectless()) {
            printf("PRE: successful communication exchange\n");
        } else {
            printf("PRE: failure communication exchange\n");
        }
        break;
    }
    case COM_PKT_CMD_POWER_OFF_TEST: {

        printf("power on/off Start..");
        g_emv_test.poweroff_test = TRUE;

        memcpy(&g_emv_test.opt_count, &ppkt->datu.dat[1], sizeof(g_emv_test.opt_count));
        g_emv_test.opt_count=htonl(g_emv_test.opt_count);

        if (g_emv_test.opt_count == 0)
        {
            g_emv_test.opt_count = 0xffffffff;
        }
        else
        {

        }

        printf("count: %d\n", g_emv_test.opt_count);

        break;
    }
    case COM_PKT_CMD_WUPA_RATS_TEST: {
        hal_nfc_config(EMV_typeA_configs, sizeof(EMV_typeA_configs)/sizeof(hal_nfc_regval_t));
        hal_nfc_antenna_on();
        g_emv_test.wupa_rats_test = 1;

        memcpy(&g_emv_test.opt_count, &ppkt->datu.dat[1], sizeof(g_emv_test.opt_count));
        g_emv_test.opt_count=htonl(g_emv_test.opt_count);

        if (g_emv_test.opt_count == 0)
        {
            g_emv_test.opt_count = 0xffffffff;
        }
        else

        {

        }

        break;
    }
    case COM_PKT_CMD_WUPB_ATTRIB_TEST: {
        hal_nfc_config(EMV_typeB_configs, sizeof(EMV_typeB_configs)/sizeof(hal_nfc_regval_t));
        hal_nfc_antenna_on();
        g_emv_test.wupb_attrib_test = 1;
        memcpy(&g_emv_test.opt_count, &ppkt->datu.dat[1], sizeof(g_emv_test.opt_count));
        g_emv_test.opt_count=htonl(g_emv_test.opt_count);

        if (g_emv_test.opt_count == 0)
        {
            g_emv_test.opt_count = 0xffffffff;
        }
        else
        {

        }

        break;
    }
    case COM_PKT_CMD_TRANSAC_A_TEST: {
        hal_nfc_config(EMV_typeA_configs, sizeof(EMV_typeA_configs)/sizeof(hal_nfc_regval_t));
        hal_nfc_antenna_on();
        g_emv_test.transac_a = 1;
        memcpy(&g_emv_test.opt_count, &ppkt->datu.dat[1], sizeof(g_emv_test.opt_count));
        g_emv_test.opt_count=htonl(g_emv_test.opt_count);

        if (g_emv_test.opt_count == 0)
        {
            g_emv_test.opt_count = 0xffffffff;
        }
        else
        {

        }

        break;
    }
    case COM_PKT_CMD_TRANSAC_B_TEST: {
        hal_nfc_config(EMV_typeA_configs, sizeof(EMV_typeA_configs)/sizeof(hal_nfc_regval_t));
        hal_nfc_antenna_on();
        g_emv_test.transac_b = 1;
        memcpy(&g_emv_test.opt_count, &ppkt->datu.dat[1], sizeof(g_emv_test.opt_count));
        g_emv_test.opt_count=htonl(g_emv_test.opt_count);
        if (g_emv_test.opt_count == 0)
        {
            g_emv_test.opt_count = 0xffffffff;
        }
        else
        {

        }

        break;
    }

    default:
        break;
    }
}

void emv_task(void)
{
    emv_analog_loop();

    if (g_emv_runing == TRUE)
    {
        emv_contectless();
    }
}

